package com.zhixun.mobile.modules.jiujiudevice;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

import com.boxin.ims.modules.jiujiudevice.entity.JiuCashConfig;
import com.boxin.ims.modules.jiujiudevice.entity.JiuCashRecord;
import com.boxin.ims.modules.jiujiudevice.service.JiuCashConfigService;
import com.boxin.ims.modules.jiujiudevice.service.JiuCashRecordService;
import com.boxin.ims.modules.wechat.entity.JiuWechatMember;
import com.boxin.ims.modules.wechat.entity.WXPay;
import com.boxin.ims.modules.wechat.entity.WeChat;
import com.boxin.ims.modules.wechat.service.JiuWechatMemberService;
import com.boxin.ims.modules.wechat.service.WXPayService;
import com.boxin.ims.modules.wechat.service.WeChatService;
import com.boxin.ims.modules.wechat.utils.JsTicketUtils;
import com.boxin.ims.modules.wechat.utils.WechatCacheUtils;
import com.boxin.ims.modules.wechat.utils.WechatInterfaceUtils;
import com.boxin.ims.modules.wechat.utils.WechatUtils;
import com.boxin.ims.modules.wechat.utils.XMLUtils;
import com.phoenix.fly.util.StringUtils;
import com.thinkgem.jeesite.common.config.Global;
import com.thinkgem.jeesite.common.utils.CacheUtils;
import com.thinkgem.jeesite.common.utils.RequestUtil;
import com.wxpay.client.util.CommonUtil;
import com.wxpay.client.util.WelfareUtils;
import com.wxpay.client.util.WxPayHelper;
import com.zhixun.mobile.modules.base.web.BaseController;

/**
 * 处理用户押金
 * 
 * @author dongchao
 *
 */
@Controller
@RequestMapping(value = Global.FRONT_PATH + "/jiujiudevice")
public class JiuJiuMemberCashFrontController extends BaseController {

	private Logger log = LoggerFactory.getLogger(JiuJiuMemberCashFrontController.class);

	public static final Long USER_ID = 2L;

	@Autowired
	private WXPayService wxPayService;
	@Autowired
	private WeChatService weChatService;
	/**
	 * 微信用户member
	 */
	@Autowired
	private JiuWechatMemberService jiuWechatMemberService;
	/**
	 * 押金记录
	 */
	@Autowired
	private JiuCashRecordService jiuCashRecordService;

	/**
	 * 押金全局配置
	 */
	@Autowired
	private JiuCashConfigService jiuCashConfigService;

	@RequestMapping(value = "jiaoyajin")
	public String jiaoyajin(HttpServletRequest request, HttpServletResponse response, Model model) {
		String openId = getOpenId("userinfo_openid", request);
		if (StringUtils.isEmpty(openId)) {
			// 拉取授权
			System.err.println("拉取了授权方法===》" + openId);
			String url = WechatUtils.getOAuthUrl("/jiujiudevice/jiaoyajin", USER_ID, request, response);
			return "redirect:" + url;
		}

		JiuWechatMember member = getMember(USER_ID, openId);
		if (member == null) {
			// 拉取授权
			System.err.println("拉取了授权方法===》" + openId);
			String url = WechatUtils.getOAuthUrl("/jiujiudevice/jiaoyajin", USER_ID, request, response);
			return "redirect:" + url;
		}

		if (StringUtils.isEmpty(member.getMobile())) {
			return "redirect:" + Global.FRONT_PATH + "/jiujiudevice/login";
		}
		JiuCashConfig jiuCashConfig = jiuCashConfigService.get();

		// 创建押金预支付订单
		JiuCashRecord jiuCashRecord = new JiuCashRecord();
		jiuCashRecord.setMemberId(member.getId());
		jiuCashRecord.setMemberMobile(member.getMobile());
		jiuCashRecord.setMemberName(member.getName());
		jiuCashRecord.setMemberNickname(member.getNickname());
		jiuCashRecord.setMemberOpenId(member.getOpenId());

		// 未支付
		jiuCashRecord.setPayStatus(0);
		jiuCashRecord.setStatus(0);

		jiuCashRecord.setMoney(jiuCashConfig.getMoney());
		jiuCashRecord.setOrderNo(JiuCashRecord.generateOrderNo());
		jiuCashRecordService.save(jiuCashRecord);

		// 提交 微信预支付订单
		createJsApi(jiuCashRecord, request, model);

		model.addAttribute("jiuCashConfig", jiuCashConfig);
		model.addAttribute("member", member);
		model.addAttribute("jiuCashRecord", jiuCashRecord);
		return "modules/jiujiudeviceFront/jiaoyajin";
	}

	/**
	 * 押金管理
	 * @param request
	 * @param response
	 * @param model
	 * @return
	 */
	@RequestMapping(value = "cashManager")
	public synchronized String cashManager(HttpServletRequest request, HttpServletResponse response, Model model) {
		String openId = getOpenId("userinfo_openid", request);
		if (StringUtils.isEmpty(openId)) {
			// 拉取授权
			System.err.println("拉取了授权方法===》" + openId);
			String url = WechatUtils.getOAuthUrl("/jiujiudevice/cashManager", USER_ID, request, response);
			return "redirect:" + url;
		}

		JiuWechatMember member = getMember(USER_ID, openId);
		if (member == null) {
			// 拉取授权
			System.err.println("拉取了授权方法===》" + openId);
			String url = WechatUtils.getOAuthUrl("/jiujiudevice/cashManager", USER_ID, request, response);
			return "redirect:" + url;
		}

		if (StringUtils.isEmpty(member.getMobile())) {
			return "redirect:" + Global.FRONT_PATH + "/jiujiudevice/login";
		}
		
		JiuCashRecord cashRecordCondtion = new JiuCashRecord();
		cashRecordCondtion.setStatus(JiuCashRecord.STATUS_YES_PAY);
		cashRecordCondtion.setMemberId(member.getId());
		List<JiuCashRecord> list = jiuCashRecordService.find(cashRecordCondtion);
		System.out.println("list = " +list);
		System.out.println("list.size=" + list.size());
		if(list.size() < 1) {
			return "redirect:" + Global.FRONT_PATH + "/jiujiudevice/jiaoyajin";
		}
		JiuCashRecord jiuCashRecord = list.get(0);
		
		model.addAttribute("jiuCashRecord", jiuCashRecord);
		model.addAttribute("member", member);
		return "modules/jiujiudeviceFront/cashManager";
	}
	
	@RequestMapping("tuiyajin")
	public String tuiyajin(HttpServletRequest request,HttpServletResponse response,RedirectAttributes redirectAttributes) {
		String openId = getOpenId("userinfo_openid", request);
		if (StringUtils.isEmpty(openId)) {
			// 拉取授权
			System.err.println("拉取了授权方法===》" + openId);
			String url = WechatUtils.getOAuthUrl("/jiujiudevice/tuiyajin", USER_ID, request, response);
			return "redirect:" + url;
		}
		
		JiuWechatMember member = getMember(USER_ID, openId);
		if(member == null) {
			// 拉取授权
			System.err.println("拉取了授权方法===》" + openId);
			String url = WechatUtils.getOAuthUrl("/jiujiudevice/tuiyajin", USER_ID, request, response);
			return "redirect:" + url;
		}
		
		//验证用户押金
		JiuCashRecord cashRecordCondtion = new JiuCashRecord();
		cashRecordCondtion.setMemberId(member.getId());
		cashRecordCondtion.setStatus(1);
		List<JiuCashRecord> list = jiuCashRecordService.find(cashRecordCondtion);
		if(list.size() == 0) {
			redirectAttributes.addAttribute("errorMsg", "操作失败，没有支付押金");
			return "redirect:" + Global.FRONT_PATH + "/jiujiudevice/jiaoyajin";
		}
		JiuCashRecord cashRecord = list.get(0);
		
		String orderNO = cashRecord.getOrderNo();
		Double money = cashRecord.getMoney()*100;
		
		try {
			Map<String, String> result = WelfareUtils.applyRefund(USER_ID,orderNO , null, orderNO, money.intValue(), money.intValue());
			 if("SUCCESS".equals(result.get("return_code"))) {
					System.out.println(4);
					
					if("SUCCESS".equals(result.get("result_code"))) {
						System.out.println(5);
						//退款成功
						cashRecord.setStatus(2);
						cashRecord.setRefundTime(new Date());
						cashRecord.setRefundStatus(1);
						jiuCashRecordService.save(cashRecord);
						sendMessage(response,"退押金成功！",Global.FRONT_PATH + "/jiujiudevice/usercenter");
						//redirectAttributes.addAttribute("errorMsg", "退款成功！");
					}else {
						//FAIL 提交业务失败
						//错误编码
						String err_code = result.get("err_code");
						//错误描述
						String err_code_des = result.get("err_code_des");
						
						cashRecord.setRefundStatus(0);
						cashRecord.setRefundErrorCode(err_code);
						cashRecord.setRefundErrorMsg(err_code_des);
						
						jiuCashRecordService.save(cashRecord);
						sendMessage(response,"退押金失败"+err_code_des+"！",Global.FRONT_PATH + "/jiujiudevice/cashManager");
						//redirectAttributes.addAttribute("errorMsg", "退款失败！");
						log.error("用户【{}】退押金失败,提交业务失败;错误编码【{}】错误描述【{}】",member.getOpenId(),err_code,err_code_des);
					}
					
				} else {
					//通信失败
					String return_msg =  result.get("return_msg");
					sendMessage(response,"退押金失败！",Global.FRONT_PATH + "/jiujiudevice/cashManager");
					//redirectAttributes.addAttribute("errorMsg", "退款失败！");
					log.error("用户【{}】退押金失败,通信失败;错误信息【{}】",member.getOpenId(),return_msg);
				}
		}catch (Exception e) {
			log.error("用户【{}】退押金失败,系统异常;错误信息【{}】",member.getOpenId(),e.getMessage());
			e.printStackTrace();
			sendMessage(response,"退押金失败！",Global.FRONT_PATH + "/jiujiudevice/cashManager");
			//return "redirect:" + Global.FRONT_PATH + "/jiujiudevice/cashManager";
		}
		
		return null;
	}

	public void sendMessage(HttpServletResponse response,String message , String redirectUrl) {
		PrintWriter print = null;
		try {
			 response.setContentType("text/html;charset=utf-8");
			 print = response.getWriter();
			 print.write("<script type=\"text/javascript\">alert(\"" +message+"\");location.href='"+redirectUrl+"'</script>");
		} catch (IOException e) {
			e.printStackTrace();
		}finally {
			print.flush();
			print.close();
		}
	}
	/**
	 * 根据USERID获取weChat
	 * 
	 * @param request
	 * @param user
	 * @return
	 */
	public WeChat getWeChat(HttpServletRequest request, Long userId) {
		WeChat weChat = (WeChat) CacheUtils.get("we_chat_" + userId);
		if (weChat == null) {
			weChat = weChatService.getWeChatByUserId(userId);
			CacheUtils.put("we_chat_" + userId, weChat);
		}
		return weChat;
	}

	/**
	 * 生成访问微信支付jsapi 押金支付 微信下单
	 * 
	 * @param model
	 * @param rechargeOrder
	 * @param request
	 * @return
	 */
	private String createJsApi(JiuCashRecord order, HttpServletRequest request, Model model) {
		String JSAPI = "";
		WXPay wxPay = wxPayService.getByUserId(USER_ID);
		if (wxPay == null) {
			request.setAttribute("message", "商户配置不正确！");
		} else {
			
			// 微信支付jsapi 生成json
			WeChat weChat = getWeChat(request, USER_ID);
			String nonce_str = CommonUtil.CreateNoncestr();
			String basePath = request.getScheme() + "://" + request.getServerName() + request.getContextPath();
			System.out.println("======createJsApi============");
			System.out.println("apiKey="+wxPay.getApiKey());
			System.out.println("appId=" + weChat.getAppId());
			System.out.println("mchId=" + wxPay.getMchId());
			System.out.println("==================");
			WxPayHelper wxPayHelper = new WxPayHelper();
			wxPayHelper.setApiKey(wxPay.getApiKey());
			wxPayHelper.setAppId(weChat.getAppId());
			wxPayHelper.setMchId(wxPay.getMchId());
			wxPayHelper.SetParameter("nonce_str", nonce_str);
			wxPayHelper.SetParameter("body", "支付押金");
			wxPayHelper.SetParameter("out_trade_no", order.getOrderNo());

			wxPayHelper.SetParameter("total_fee", String.format("%.0f", order.getMoney() * 100));

			wxPayHelper.SetParameter("spbill_create_ip", RequestUtil.getUserIpAddr(request));
			wxPayHelper.SetParameter("notify_url", basePath + "/f/jiujiudevice/wxNotifyForCash");
			wxPayHelper.SetParameter("trade_type", "JSAPI");
			wxPayHelper.SetParameter("openid", order.getMemberOpenId());
			try {
				JSAPI = wxPayHelper.createPayUrlByJSAPI();
			} catch (Exception e) {
				log.error(e.getMessage(), e);
			}
			model.addAttribute("JSAPI", JSAPI);
			log.info("JSAPI:" + JSAPI);
		}
		return JSAPI;
	}

	/**
	 * 查询微信订单
	 * 
	 * @param order
	 * @param request
	 * @return
	 */
	private Map<String, String> findPayUrlByJSAPI(String orderNO, HttpServletRequest request) {
		WXPay wxPay = wxPayService.getByUserId(USER_ID);
		if (wxPay == null) {
			request.setAttribute("message", "商户配置不正确！");
		} else {
			// 微信支付jsapi 生成json
			WeChat weChat = getWeChat(request, USER_ID);
			WxPayHelper wxPayHelper = new WxPayHelper();
			wxPayHelper.setApiKey(wxPay.getApiKey());
			wxPayHelper.setAppId(weChat.getAppId());
			wxPayHelper.setMchId(wxPay.getMchId());
			wxPayHelper.SetParameter("nonce_str", CommonUtil.CreateNoncestr());
			wxPayHelper.SetParameter("out_trade_no", orderNO);

			try {
				return wxPayHelper.findPayUrlByJSAPI();
			} catch (Exception e) {
				log.error(e.getMessage(), e);
			}
		}
		return null;
	}
	/**
	 * 
	 * @function:
	 *            <p>
	 *            wx.config({ debug: true, //
	 *            开启调试模式,调用的所有api的返回值会在客户端alert出来，若要查看传入的参数，可以在pc端打开，
	 *            参数信息会通过log打出，仅在pc端时才会打印。 appId: '', // 必填，公众号的唯一标识 timestamp: , //
	 *            必填，生成签名的时间戳 nonceStr: '', // 必填，生成签名的随机串 signature: '',// 必填，签名
	 *            jsApiList: [] // 必填，需要使用的JS接口列表 });
	 *            </p>
	 * @param request
	 * @param userId
	 */
	public void getJsapiTicket(HttpServletRequest request, Long userId) {
		WeChat weChat = WechatCacheUtils.getWeChatByUserId(userId);
		// jsapi ticket 生成
		String ticket = JsTicketUtils.getJSAPITicket(weChat);
		// 获取路径
		String url = request.getRequestURL() + "";
		if (request.getQueryString() != null) {
			url += "?" + request.getQueryString();
		}
		/*
		 * System.err.println("js参与参数"+url);
		 */ Map<String, String> result = new HashMap<String, String>();
		result = WechatInterfaceUtils.sign(ticket, url);
		request.setAttribute("signature", result.get("signature"));
		request.setAttribute("nonceStr", result.get("nonceStr"));
		request.setAttribute("timestamp", result.get("timestamp"));
		request.setAttribute("weChatAppId", weChat.getAppId());
	}

	/**
	 * 微信支付回调 押金支付回调
	 * 
	 * @param request
	 * @param response
	 * @param model
	 * @return
	 * @throws Exception
	 */
	@ResponseBody
	@RequestMapping(value = "wxNotifyForCash")
	public String wxNotifyForCash(HttpServletRequest request, HttpServletResponse response, Model model)
			throws Exception {

		StringBuffer stringBuffer = new StringBuffer();
		BufferedReader bReader = request.getReader();
		String line = "";
		while ((line = bReader.readLine()) != null) {
			stringBuffer.append(line);
		}
		Map<String, String> xmlMap = XMLUtils.xml2Map(stringBuffer.toString());

		String resXml = null;

		if ("SUCCESS".equals(xmlMap.get("xml.result_code"))) {
			String orderNo = xmlMap.get("xml.out_trade_no");
		
			JiuCashRecord order = jiuCashRecordService.findByOrderNo(orderNo);
			// 验证
			Map<String, String> result = findPayUrlByJSAPI(order.getOrderNo(), request);
			System.out.println("=======订单查询=================");
			System.out.println(result);
			System.out.println("========================");
			if (!"SUCCESS".equals(result.get("return_code"))) {
				log.error("订单-【" + orderNo + "】支付失败,调用查询接口失败,网络不通");
				return "<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[支付失败]]></return_msg></xml>";
			}

			if (!"SUCCESS".equals(result.get("result_code"))) {
				log.error("订单-【" + orderNo + "】支付失败,调用查询接口失败，err_code=" + result.get("err_code") + "|" + "err_code_des="
						+ result.get("err_code_des"));
				return "<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[支付失败]]></return_msg></xml>";
			}
			// 验证交易状态
			String trade_state = result.get("trade_state");
			if (!"SUCCESS".equals(trade_state)) {
				// 交易失败
				log.error("订单-【" + orderNo + "】支付失败 trade_state=" + trade_state);
				resXml = "<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[支付失败]]></return_msg></xml>";
			}
			
			// 支付成功后 验证 支付金额
			String total_fee = result.get("total_fee");
			System.out.println("==========支付金额================="+total_fee);
			if (total_fee.equals(String.format("%.0f", order.getMoney() * 100))) {
				String transactionId = xmlMap.get("xml.transaction_id");
				// 支付金额 正确
				// 处理业务逻辑
				order.setStatus(JiuCashRecord.STATUS_YES_PAY);
				order.setPayStatus(JiuCashRecord.PAY_STATUS_SUCCESS);
				order.setTransactionId(transactionId);
				order.setPayTime(new Date());
				System.out.println("status = "+order.getStatus());
				System.out.println("payStatus = "+order.getPayStatus());
				jiuCashRecordService.save(order);
				System.out.println("==========支付成功=================");
			} else {
				order.setStatus(JiuCashRecord.STATUS_NO_PAY);
				order.setPayStatus(JiuCashRecord.PAY_STATUS_FAIL);
				order.setErrorMsg("支付失败， 支付金额错误；应付金额【" + String.format("%.0f", order.getMoney() * 100) +"】实付金额【" + total_fee + "】");
				resXml = "<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[支付失败]]></return_msg></xml>";
				log.error("订单-【" + orderNo + "】" + order.getErrorMsg());
			}
			

			resXml = "<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>";
		} else {
			resXml = "<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[支付失败]]></return_msg></xml>";
		}
		return resXml;
	}
	
	/** 从缓存获取会员 */
	public JiuWechatMember getMember(Long uid, String openId) {

		JiuWechatMember member = (JiuWechatMember) CacheUtils.get(openId);
		if (member == null) {
			member = jiuWechatMemberService.getByUserIdAndOpenId(uid, openId);
			CacheUtils.put(openId, member);
		}
		return member;
	}
}
